package edu.vt.ece.rt.quorum.messsages.types;

import org.jgroups.Address;
import org.jgroups.Message;

import edu.vt.ece.rt.dstm.Context;
import edu.vt.ece.rt.dstm.ContextDelegator;
import edu.vt.ece.rt.dstm.QObject;
import edu.vt.ece.rt.dstm.TMProxy;
import edu.vt.ece.rt.quorum.ClustersManager;
import edu.vt.ece.rt.quorum.Resource;
import edu.vt.ece.rt.quorum.messsages.QMessage;
import edu.vt.ece.rt.quorum.messsages.QMessage.MessageType;
import edu.vt.ece.rt.quorum.util.Names;
import edu.vt.ece.rt.util.Logger.Logger;

/*
 * Read Request to all the nodes in read Quorum
 * @author Sudhanshu
 */

public class ReadRequest extends QMessage implements Runnable {
	String Id;			//Specify the Object Id to be received
	public Long txnId; 		//Specify the transaction number, Can be Converted to Context Class, if some MetaData required
	Long txnIdParent; 		//parent txn ID
	boolean read;		//Specify read or write 
	int requesterID;		//Specify the cluster on which response will be unicast back
	

	public ReadRequest(String id, Long tid, Long tidParent, boolean rw, int rid, String mId) {
		super(MessageType.ReadRequest);
		Id = id;
		txnId = tid;
		txnIdParent = tidParent;
		read = rw;
		requesterID = rid;
		messageId = mId;
	}
	
	@Override
	public void run() {
		//Get Object
		Logger.debug("Running the "+ (read?"Read":"write")+" Request of "+ Id + " for " + txnId+ " from "+requesterID +" with parent as "+txnIdParent);
		QObject qObj = null;
		synchronized (Resource.waitObj) {
			qObj = Resource.getQObject(Id);
			if (!qObj.isProtected(txnId)) {
				qObj = qObj.clone();				
			} else {
				qObj = null;
			}
		
		//Add Context to potential read-write list
		if (qObj != null) {
			if(read == true){		//Read request
				Context c = ContextDelegator.getContext(txnId);
				Resource.addPR(Id, c);
				c.addToReadSet(qObj);
				c.setParent(txnIdParent);
				Logger.debug("Added "+txnId+ " as potential reader of "+qObj.getId());
			} else{
				Context c = ContextDelegator.getContext(txnId);
				Resource.addPW(Id, c);
				c.addToWriteSet(qObj);
				c.setParent(txnIdParent);
				Logger.debug("Added "+txnId+ " as potential writer of "+qObj.getId());
			}
		}
		
		}
		//Send back the response to node
		try {
//			if (qObj == null) {
//				Logger.debug("Repling with null object");
//			}
//			if(read)
				ClustersManager.getCluster(requesterID+Names.readQuorum).send(new Message(getSrcAddr(), new ReadResponse(Id, txnId, qObj, read)));
//			else
//				ClustersManager.getCluster(requesterID+Names.writeQuorum).send(new Message(getSrcAddr(), new ReadResponse(Id, txnId, qObj, read)));
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
